using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet.Models;
using DockerPlay;
using Sustainalytics.MongoDB.Extensions;
using Xunit;
using Xunit.Sdk;
using ConnectionStrings = DockerPlay.ConnectionStrings;


namespace Tests
{
    public class DockerOrchestratorTests
    {
        private readonly DockerOrchestrator dockerOrchestrator;
        private readonly DockerHelper dockerHelper;

        public DockerOrchestratorTests()
        {
            dockerHelper = new DockerHelper(ConnectionStrings.DockerMachineGA);
            dockerOrchestrator = new DockerOrchestrator(dockerHelper);
        }

        [Fact]
        public async Task StartMongoQueryRouter()
        {
            await dockerHelper.StartContainer(ContainerName.config_server);
            await dockerHelper.StartContainer(ContainerName.query_router);
        }

        [Fact]
        public async Task StartSyncContainer_Should_StartSyncContainer()
        {
            await dockerOrchestrator.StartSyncContainer(ContainerName.ga_mongo_a_27017);
            var status = await dockerHelper.GetContainerStatus(ContainerName.ga_mongo_b_27018);

            Assert.Equal(status, DockerContainerState.running);
        }

        [Fact]
        public async Task SwitchContainers()
        {
            var activeContainer = await dockerHelper.GetActiveContainer();
            var mongoWriteCollection = MongoFactory.GetCollectionFromDatabase<ContainerStatus>(ConnectionStrings.ClientPlatform);
            ContainerStatus containerStatus = null;

            if (activeContainer == ContainerName.ga_mongo_b_27017)
            {
                containerStatus = await ChageTo_A_when_B_is_active();

            }
            if (activeContainer == ContainerName.ga_mongo_a_27017)
            {
                containerStatus = await ChageTo_B_when_A_is_active();
            }

            await mongoWriteCollection.InsertOneAsync(containerStatus);

        }

        public async Task<ContainerStatus> ChageTo_B_when_A_is_active()
        {
            var activeContainer = ContainerName.ga_mongo_a_27017;

            await dockerOrchestrator.StartSyncContainer(activeContainer);

            var containersAfterStartSync = await dockerHelper.GetContainersIdAndStatus();

            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_a_27017).State, DockerContainerState.running);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_b_27018).State, DockerContainerState.running);

            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_b_27017).State, DockerContainerState.exited);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_a_27018).State, DockerContainerState.exited);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_backup_from_a).State, DockerContainerState.exited);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_backup_from_b).State, DockerContainerState.exited);

            var newActiveContainer = await dockerOrchestrator.SwitchActiveContainer(activeContainer);

            var containersAfterEndSync = await dockerHelper.GetContainersIdAndStatus();


            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_a_27017).State, DockerContainerState.exited);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_b_27018).State, DockerContainerState.exited);

            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_b_27017).State, DockerContainerState.running);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_a_27018).State, DockerContainerState.exited);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_backup_from_a).State, DockerContainerState.exited);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_backup_from_b).State, DockerContainerState.exited);

            return containersAfterEndSync.First(x => x.Name == newActiveContainer);

        }

        public async Task<ContainerStatus> ChageTo_A_when_B_is_active()
        {
            var activeContainer = ContainerName.ga_mongo_b_27017;

            await dockerOrchestrator.StartSyncContainer(activeContainer);

            var containersAfterStartSync = await dockerHelper.GetContainersIdAndStatus();

            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_b_27017).State, DockerContainerState.running);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_a_27018).State, DockerContainerState.running);

            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_a_27017).State, DockerContainerState.exited);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_mongo_b_27018).State, DockerContainerState.exited);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_backup_from_a).State, DockerContainerState.exited);
            Assert.Equal(containersAfterStartSync.First(x => x.Name == ContainerName.ga_backup_from_b).State, DockerContainerState.exited);



            var newActiveContainer = await dockerOrchestrator.SwitchActiveContainer(activeContainer);

            var containersAfterEndSync = await dockerHelper.GetContainersIdAndStatus();


            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_a_27017).State, DockerContainerState.running);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_b_27018).State, DockerContainerState.exited);

            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_b_27017).State, DockerContainerState.exited);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_mongo_a_27018).State, DockerContainerState.exited);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_backup_from_a).State, DockerContainerState.exited);
            Assert.Equal(containersAfterEndSync.First(x => x.Name == ContainerName.ga_backup_from_b).State, DockerContainerState.exited);
            return containersAfterEndSync.First(x => x.Name == newActiveContainer);

        }
    }
}